package pers.dawnyang.modular.system.controller;

import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import com.baomidou.kaptcha.Kaptcha;
import lombok.extern.slf4j.Slf4j;
import pers.dawnyang.common.annotation.OperLog;
import pers.dawnyang.common.constant.Const;
import pers.dawnyang.common.domain.Result;
import pers.dawnyang.common.domain.entity.SysLoginLog;
import pers.dawnyang.common.enums.ConfigEnum;
import pers.dawnyang.common.enums.OperType;
import pers.dawnyang.common.enums.ResultEnum;
import pers.dawnyang.common.util.ResultUtil;
import pers.dawnyang.config.cache.ConfigUtils;
import pers.dawnyang.modular.system.domain.common.LoginReq;
import pers.dawnyang.modular.system.domain.common.LoginRes;
import pers.dawnyang.modular.system.service.LoginService;

/**
 * 登录页面
 * 
 * @author dawn yang
 * @date 2021/03/11
 */

@Slf4j
@Controller
@RequestMapping("/")
public class LoginController {

  @Autowired
  private Kaptcha kaptcha;

  @Autowired
  private LoginService loginService;

  @Value("${shiro.config.rememberme}")
  private Boolean rememberme;


  /**
   * 登录页
   * 
   * @return
   */
  @OperLog(operModul = "登录页面", operType = OperType.OTHER)
  @GetMapping("/login")
  public ModelAndView login() {
    ModelAndView mav = new ModelAndView();
    String captchaSwitch = ConfigUtils.getValue(ConfigEnum.CAPTCHA_SWITCH.getConfigCode());
    mav.addObject("captchaSwitch", captchaSwitch);
    mav.addObject("remembermeSwitch", rememberme);
    mav.setViewName("base/login/loginView");
    return mav;
  }

  /**
   * 验证码请求
   */
  @GetMapping("/kaptcha/render")
  public void render() {
    kaptcha.render();
  }

  /**
   * 执行登录提交
   * 
   * @param request
   * @param loginReq
   * @return
   */
  @OperLog(operModul = "登录操作", operType = OperType.OTHER)
  @PostMapping("/doLogin")
  @ResponseBody
  public Result<LoginRes> doLogin(HttpServletRequest request, @Validated LoginReq loginReq) {
    LoginRes loginRes = new LoginRes();
    String userCode = loginReq.getUserCode();
    String userPwd = loginReq.getUserPwd();
    // 检查是否开启验证码
    String captchaSwitch = ConfigUtils.getValue(ConfigEnum.CAPTCHA_SWITCH.getConfigCode());
    if (captchaSwitch.equals(ConfigEnum.CAPTCHA_SWITCH.getConfigValue())) {
      String validcode = loginReq.getValidcode();
      try {
        kaptcha.validate(validcode);
      } catch (Exception e1) {
        SysLoginLog loginInfo = loginService.setLoginInfo(request, userCode, Const.LOGIN_TYPE_PWD,
            Const.LOGIN_FAIL, ResultEnum.ERROR_VALIDCODE.getMsg());
        loginService.recordLogin(loginInfo);
        loginRes.setHrefUrl("login");
        return ResultUtil.error(ResultEnum.ERROR_VALIDCODE, loginRes);
      }
    }

    Subject subject = SecurityUtils.getSubject();
    UsernamePasswordToken auth = new UsernamePasswordToken(userCode, userPwd);

    try {

      // 设置记住我（用户信息太大，超过浏览器cookie的4k最大值时，不生效）
      Integer loginType = Const.LOGIN_TYPE_PWD;
      if (rememberme && StringUtils.isNotBlank(loginReq.getRememberMe())
          && "on".equals(loginReq.getRememberMe())) {
        auth.setRememberMe(true);
        loginType = Const.LOGIN_TYPE_RM;
      }

      subject.login(auth);
      // 记录登录日志
      SysLoginLog sysLoginLog =
          loginService.setLoginInfo(request, userCode, loginType, Const.LOGIN_SUCCESS, "");
      loginService.recordLogin(sysLoginLog);
      loginRes.setHrefUrl("index");
      return ResultUtil.success(loginRes);
    } catch (Exception e) {
      e.printStackTrace();
      SysLoginLog loginInfo = loginService.setLoginInfo(request, userCode, Const.LOGIN_TYPE_PWD,
          Const.LOGIN_FAIL, ResultEnum.ERROR_USERPWD.getMsg());
      loginService.recordLogin(loginInfo);
      loginRes.setHrefUrl("login");
      return ResultUtil.error(ResultEnum.ERROR_USERPWD, loginRes);
    }
  }

  @GetMapping("/logout")
  public String logout(HttpServletRequest request) {
    Subject subject = SecurityUtils.getSubject();
    subject.logout();
    return "redirect:login";
  }

}
